%{
#include "frcmd_parse.h"

typedef char* string;
#define YYSTYPE string

YYSTYPE yylval;
%}

%token TERMINATOR
%token SETUP COMMIT ROLLBACK PRINT EXPORT EXIT SERVER_EXIT HELP
%token L7 L7_DEFAULT FILTER JAVA SYSTEM MEMORY CT TOPOLOGY MODULE MODULE_DEFAULT SERVER THREAD PCAP
%token ADD DEL CLEAR
%token INTEGER STRING IPPROTO FILENAME IPADDR MACADDR IPRANGE PORTRANGE

%%

program:
        function
        ;

function:
          function stmt
        | /* NULL */
        | error TERMINATOR  /* Ignore Error */
        ;
        
stmt:
		  TERMINATOR
        | stmt_setup
        | stmt_commit
        | stmt_rollback
        | stmt_print
        | stmt_export
        | stmt_help
        | stmt_server_exit
        | stmt_exit
        ;

ipproto_or_empty:
	  /* Empty */ { $$ = NULL; }
	| IPPROTO
	;

iprange_portrange:
  	  ipaddr_or_range port_or_range { $$ = contact_ipport($1,$2); }
  	| ipaddr_or_range
  	;
  	
ipaddr_or_range:
	  IPADDR
	| IPRANGE
	;
	
ipaddr_or_empty:
	  /* Empty */ { $$ = NULL; }
	| IPADDR
	;	
		
port_or_range:
      INTEGER
    | PORTRANGE
    ;
    
/* setup cmd */
stmt_setup:
          stmt_setup_l7
        | stmt_setup_filter
        | stmt_setup_java
        | stmt_setup_module
        ;


/* setup l7 cmd [ip_proto] ip port l7_proto */
stmt_setup_l7:
	  stmt_add_l7
	| stmt_default_l7
	| stmt_del_l7
	| stmt_clear_l7
	| stmt_clear_l7_default
	;  
stmt_add_l7:
      SETUP L7 ADD ipproto_or_empty IPADDR port_or_range STRING TERMINATOR { l7_add($4, $5, $6, $7); }
    | SETUP L7 ADD ipproto_or_empty IPADDR port_or_range INTEGER TERMINATOR { l7_add($4, $5, $6, $7); }
	| SETUP L7 ADD ipproto_or_empty IPADDR port_or_range TERMINATOR { l7_add($4, $5, $6, NULL); }
	;
stmt_default_l7:
	  SETUP L7_DEFAULT ADD ipproto_or_empty STRING TERMINATOR { l7_default_add($4, $5); }
	| SETUP L7_DEFAULT ADD ipproto_or_empty INTEGER TERMINATOR { l7_default_add($4, $5); }
	| SETUP L7_DEFAULT DEL ipproto_or_empty TERMINATOR { l7_default_del($4); }
	;
stmt_del_l7:
	  SETUP L7 DEL ipproto_or_empty IPADDR port_or_range TERMINATOR { l7_del($4, $5, $6); }
	;
stmt_clear_l7:
	  SETUP L7 CLEAR TERMINATOR { l7_clear(); }
	;
stmt_clear_l7_default:
	  SETUP L7_DEFAULT CLEAR TERMINATOR { l7_default_clear(); }
	;
		
/* setup module cmd soname l7_proto l7_proto_name mem_size */
stmt_setup_module:
	  stmt_add_module
	| stmt_del_module
	| stmt_clear_module
	;
stmt_add_module:
      SETUP MODULE ADD FILENAME ipproto_or_empty INTEGER STRING INTEGER TERMINATOR { module_add($4, $5, atoi($6), $7, atoi($8)); }
    | SETUP MODULE ADD FILENAME ipproto_or_empty INTEGER STRING TERMINATOR { module_add($4, $5, atoi($6), $7, 50); }
	;
stmt_del_module:
	  SETUP MODULE DEL INTEGER TERMINATOR { module_del(atoi($4)); }
	;
stmt_clear_module:
	  SETUP MODULE CLEAR TERMINATOR { module_clear(); }
	;

/* 
   setup filter cmd [mac] [ip_proto] ip-range [port-range] ip-range [port-range]
   setup filter clear
 */
stmt_setup_filter:
	  stmt_add_filter
	| stmt_del_filter
	| stmt_clear_filter
	;

stmt_add_filter:
	  SETUP FILTER ADD MACADDR ipproto_or_empty iprange_portrange iprange_portrange TERMINATOR { filter_add($4, $5, $6, $7); }
	| SETUP FILTER ADD MACADDR ipproto_or_empty iprange_portrange TERMINATOR { filter_add($4, $5, $6, NULL); }  
	| SETUP FILTER ADD MACADDR ipproto_or_empty TERMINATOR { filter_add($4, $5, NULL, NULL); }
	| SETUP FILTER ADD ipproto_or_empty iprange_portrange iprange_portrange TERMINATOR { filter_add(NULL, $4, $5, $6); }
	| SETUP FILTER ADD ipproto_or_empty iprange_portrange TERMINATOR { filter_add(NULL, $4, $5, NULL); }
	;
stmt_del_filter:
	  SETUP FILTER DEL MACADDR ipproto_or_empty iprange_portrange iprange_portrange TERMINATOR { filter_del($4, $5, $6, $7); }
	| SETUP FILTER DEL MACADDR ipproto_or_empty iprange_portrange TERMINATOR { filter_del($4, $5, $6, NULL); }  
	| SETUP FILTER DEL MACADDR ipproto_or_empty TERMINATOR { filter_del($4, NULL, NULL, NULL); }  
	| SETUP FILTER DEL ipproto_or_empty iprange_portrange iprange_portrange TERMINATOR { filter_del(NULL, $4, $5, $6); }
	| SETUP FILTER DEL ipproto_or_empty iprange_portrange TERMINATOR { filter_del(NULL, $4, $5, NULL); }
	;
stmt_clear_filter:
	  SETUP FILTER CLEAR TERMINATOR { filter_clear(); }	
	;

/* setup java family [ip_proto] port */
stmt_setup_java:
	  SETUP JAVA IPPROTO ipaddr_or_empty INTEGER TERMINATOR { java_setup($3, $4, atoi($5)); }
	;
	
/* commit cmd  */	
stmt_commit:
	  COMMIT L7 TERMINATOR { commit(OBJECT_L7); }
	| COMMIT L7_DEFAULT TERMINATOR { commit(OBJECT_L7_DEFAULT); }
	| COMMIT FILTER TERMINATOR { commit(OBJECT_FILTER); }
	| COMMIT JAVA TERMINATOR { commit(OBJECT_JAVA); }
	;  	
	
/* rollback cmd */	
stmt_rollback:
	  ROLLBACK L7 TERMINATOR { rollback(OBJECT_L7); }
	| ROLLBACK L7_DEFAULT TERMINATOR { rollback(OBJECT_L7_DEFAULT); }
	| ROLLBACK FILTER TERMINATOR { rollback(OBJECT_FILTER); }
	| ROLLBACK JAVA TERMINATOR { rollback(OBJECT_JAVA); }
	;  		  

/* print cmd */
stmt_print:
	  print_system
	| print_ct	
	| print_topology
	| print_thread
	| print_module
	| print_server  
	| print_filter
	| print_l7
	| print_java
	| print_memory
	;
	
print_system:	
	  PRINT SYSTEM TERMINATOR { print_system();}
	;

print_ct:
	  PRINT CT TERMINATOR { print_ct(NULL);}  
	| PRINT CT INTEGER TERMINATOR { print_ct($3); }
	| PRINT CT STRING TERMINATOR { print_ct($3); }
	;

print_topology:
	PRINT TOPOLOGY TERMINATOR { print_topology(); }
	;

print_thread:
	PRINT THREAD TERMINATOR { print_thread(); }
	;

print_module:
	PRINT MODULE STRING TERMINATOR { print_module($3); }
	;

print_server:
	PRINT SERVER TERMINATOR { print_server(); }
	;	
	
print_filter:
	PRINT FILTER TERMINATOR { print_filter(); }
	;	
	
print_java:
	PRINT JAVA TERMINATOR { print_java(); }
	;		

print_l7:
	PRINT L7 TERMINATOR { print_l7(); }
	;	
	
print_memory:
	PRINT MEMORY TERMINATOR { print_memory(); }
	;	

/* export pcap tcp ip port */
stmt_export:
	EXPORT PCAP IPPROTO IPADDR INTEGER TERMINATOR { export_pcap($3, $4, atoi($5));}
	;
	
/* help */
stmt_help:
	  HELP    { print_help(); }
	;	  
	
/* exit/quit */		
stmt_exit:
      EXIT                      { exit(0); }
    ;

stmt_server_exit:
      SERVER_EXIT               { server_exit(); }
    ;
%%

int yyerror(char *msg)
{
	fprintf (stderr, "error: %s\n", msg);
	return 0;
}
